package com.campusbackend.service.impl;

import com.campusbackend.config.FileUploadConfig;
import com.campusbackend.service.FileUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 文件上传服务实现类
 * 
 * @author yezi
 * @since 2025-07-27
 */
@Slf4j
@Service
public class FileUploadServiceImpl implements FileUploadService {
    
    @Autowired
    private FileUploadConfig fileUploadConfig;
    
    /**
     * 支持的图片文件类型
     */
    private static final List<String> ALLOWED_IMAGE_TYPES = Arrays.asList(
            "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp"
    );
    
    /**
     * 支持的图片文件扩展名
     */
    private static final List<String> ALLOWED_IMAGE_EXTENSIONS = Arrays.asList(
            ".jpg", ".jpeg", ".png", ".gif", ".webp"
    );
    
    @Override
    public Map<String, Object> uploadImage(MultipartFile file) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证文件
            if (file.isEmpty()) {
                result.put("success", false);
                result.put("message", "文件不能为空");
                return result;
            }
            
            // 验证文件类型
            if (!isImageFile(file)) {
                result.put("success", false);
                result.put("message", "只支持上传图片文件（jpg、jpeg、png、gif、webp）");
                return result;
            }
            
            // 验证文件大小（限制10MB）
            if (!isValidFileSize(file, 10)) {
                result.put("success", false);
                result.put("message", "文件大小不能超过10MB");
                return result;
            }
            
            // 生成文件存储路径
            String uploadPath = generateUploadPath();
            String fileName = generateFileName(file.getOriginalFilename());
            String fullPath = uploadPath + File.separator + fileName;
            
            // 确保目录存在
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }
            
            // 保存文件
            Path filePath = Paths.get(fullPath);
            Files.copy(file.getInputStream(), filePath);
            
            // 生成访问URL
            String fileUrl = generateFileUrl(uploadPath, fileName);
            
            // 返回结果
            result.put("success", true);
            result.put("url", fileUrl);
            result.put("originalName", file.getOriginalFilename());
            result.put("size", file.getSize());
            result.put("fileName", fileName);
            
            log.info("文件上传成功 - 原始文件名: {}, 存储文件名: {}, 文件大小: {} bytes", 
                    file.getOriginalFilename(), fileName, file.getSize());
            
        } catch (IOException e) {
            log.error("文件上传失败", e);
            result.put("success", false);
            result.put("message", "文件上传失败：" + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public boolean deleteFile(String fileUrl) {
        try {
            // 从URL中提取文件路径
            String basePath = fileUploadConfig.getUpload().getPath();
            String relativePath = fileUrl.replace(fileUploadConfig.getAccess().getDomain() + "/files/", "");
            String fullPath = basePath + File.separator + relativePath.replace("/", File.separator);
            
            File file = new File(fullPath);
            if (file.exists()) {
                boolean deleted = file.delete();
                log.info("删除文件 {} - 结果: {}", fullPath, deleted);
                return deleted;
            } else {
                log.warn("要删除的文件不存在: {}", fullPath);
                return false;
            }
        } catch (Exception e) {
            log.error("删除文件失败: {}", fileUrl, e);
            return false;
        }
    }
    
    @Override
    public boolean isImageFile(MultipartFile file) {
        // 检查MIME类型
        String contentType = file.getContentType();
        if (contentType != null && ALLOWED_IMAGE_TYPES.contains(contentType.toLowerCase())) {
            return true;
        }
        
        // 检查文件扩展名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null) {
            String extension = originalFilename.toLowerCase();
            return ALLOWED_IMAGE_EXTENSIONS.stream().anyMatch(extension::endsWith);
        }
        
        return false;
    }
    
    @Override
    public boolean isValidFileSize(MultipartFile file, int maxSizeInMB) {
        long maxSizeInBytes = maxSizeInMB * 1024 * 1024L;
        return file.getSize() <= maxSizeInBytes;
    }
    
    /**
     * 生成上传路径（按年月日分目录）
     */
    private String generateUploadPath() {
        String basePath = fileUploadConfig.getUpload().getPath();
        String datePath = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        return basePath + File.separator + "images" + File.separator + datePath;
    }
    
    /**
     * 生成唯一文件名
     */
    private String generateFileName(String originalFilename) {
        String extension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return UUID.randomUUID().toString().replace("-", "") + extension;
    }
    
    /**
     * 生成文件访问URL
     */
    private String generateFileUrl(String uploadPath, String fileName) {
        String basePath = fileUploadConfig.getUpload().getPath();
        String relativePath = uploadPath.replace(basePath, "").replace(File.separator, "/");
        return fileUploadConfig.getAccess().getDomain() + "/files" + relativePath + "/" + fileName;
    }
}
